---
id: code-scanning
title: QR/Barcode Scanning
sidebar_label: QR/Barcode Scanning
---

import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
import useBaseUrl from '@docusaurus/useBaseUrl'

<div class="image-container">
  <svg xmlns="http://www.w3.org/2000/svg" width="283" height="535">
    <image href={useBaseUrl("img/demo.gif")} x="18" y="33" width="247" height="469" />
    <image href={useBaseUrl("img/frame.png")} width="283" height="535" />
  </svg>
</div>

## What is a Code Scanner?

A Code Scanner is a separate Camera output (just like photo or video) that can detect a variety of machine-readable codes, such as:

- **QR**: Square QR codes
- **Aztec**: Square Aztec codes
- **Data Matrix**: Square Data Matrix codes
- **Barcode (EAN)**: EAN-13 or EAN-8 Barcodes
- **Barcode (Code)**: Code-128, Code-39, or Code-93 Barcodes
- **Barcode (GS1)**: GS1 DataBar, GS1 DataBar Limited, GS1 DataBar Expanded, and their stacked versions
- **Barcode (other)**: Codabar, Interleaved 2 of 5 (ITF), ITF-14, UPC-E, or PDF-417 Barcodes

## Setup

On iOS, the Code Scanner uses the platform-native APIs and can be used out of the box.

On Android, the [MLKit Vision Barcode Scanning](https://developers.google.com/ml-kit/vision/barcode-scanning) API will be used, and the model (2.2MB) needs to be included into your app first.

<Tabs
  groupId="environment"
  defaultValue="rn"
  values={[
    {label: 'React Native', value: 'rn'},
    {label: 'Expo', value: 'expo'}
  ]}>
<TabItem value="rn">

Inside your `gradle.properties` file, add the `enableCodeScanner` flag:

```groovy
VisionCamera_enableCodeScanner=true
```

</TabItem>
<TabItem value="expo">

Add the `enableCodeScanner` flag to your Expo config (`app.json`, `app.config.json` or `app.config.js`):

```json
{
  "name": "my app",
  "plugins": [
    [
      "react-native-vision-camera",
      {
        // ...
        "enableCodeScanner": true
      }
    ]
  ]
}
```

</TabItem>
</Tabs>

## Usage

To scan codes, simply create a [`CodeScanner`](/docs/api/interfaces/CodeScanner) instance and pass it to the `<Camera>`:

<Tabs
  groupId="component-style"
  defaultValue="hooks"
  values={[
    {label: 'Hooks API', value: 'hooks'},
    {label: 'Imperative API', value: 'imperative'}
  ]}>
<TabItem value="hooks">

```tsx
const codeScanner = useCodeScanner({
  codeTypes: ['qr', 'ean-13'],
  onCodeScanned: (codes) => {
    console.log(`Scanned ${codes.length} codes!`)
  }
})

return <Camera {...props} codeScanner={codeScanner} />
```

The result of this will automatically be memoized.

</TabItem>
<TabItem value="imperative">

```ts
const codeScanner: CodeScanner = {
  codeTypes: ['qr', 'ean-13'],
  onCodeScanned: (codes) => {
    console.log(`Scanned ${codes.length} codes!`)
  }
}
```

Make sure to memoize the result of this, as every change in this will trigger a Camera session re-build.

```tsx
render() {
  return <Camera {...props} codeScanner={this.codeScanner} />
}
```

</TabItem>
</Tabs>

## Code result

The Code Scanner will call your [`onCodeScanned`](/docs/api/interfaces/CodeScanner#oncodescanned) callback with all detected codes ([`Code`](/docs/api/interfaces/Code)), including their decoded string value, and their coordinates on the screen relative to subject area of the Code Scanner (the [`frame`](/docs/api/interfaces/Code#frame)).

## UPC-A vs EAN-13 codes

UPC-A is a special case to handle if you need to cater for it. Android's SDK officially supports UPC-A but iOS does not, instead they handle the code as EAN-13. Since EAN-13 is a superset of UPC-A, with an extra 0 digit at the front.

This means, the `upc-a` types are reported under the `ean-13` umbrella type on iOS:

```jsx
const codeScanner = useCodeScanner({
  codeTypes: ['upc-a'], // <-- ✅ We configure for 'upc-a' types
  onCodeScanned: (codes) => {
    for (const code of codes) {
      console.log(code.type); // <-- ❌ On iOS, we receive 'ean-13'
    }
  }
})
```

You will need to keep this in mind and do the conversion from EAN-13 to UPC-A yourself. This can be done by removing the front `0` digit from the code to get a UPC-A code.

## Interleaved2of5 (ITF) and ITF-14

Interleaved2of5 (ITF) barcodes are supported by both, Android and iOS, where Android's SDK supports barcodes in ITF format with a minimum length of 6 characters.

ITF-14 is a sub type of interleaved2of5 which always encodes 14 characters. The ITF-14 type is only supported by iOS. If you want to have the restriction to 14 characters in Android as well, you have to handle this in your own code.

#### 🚀 Next section: [Frame Processors](frame-processors)
